home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Internet / News / Alexandra.0.82 / Source / Article.m < prev    next >
Encoding:
Text File  |  1996-01-30  |  7.4 KB  |  384 lines

  1. #import "Alexandra.h"
  2. #import "Article.h"
  3. #import "descriptors.h"
  4. #import "headerfields.h"
  5. #import "parsedate.h"
  6. #import "rfc822realname.h"
  7. #import "parse-header.h"
  8. #import "plain-subject.h"
  9.  
  10. #import <time.h>
  11. #import <misckit/MiscAppDefaults.h>
  12. #import "Preferences.subproj/preferences.h"
  13.  
  14. static BOOL showAuthor,showSubject,showSize;
  15. static int    smallIs,largeIs;
  16. static int sortType=0;
  17.  
  18. @implementation Article
  19.  
  20. + initialize                // Ein Article wird erst erzeugt nachdem das main-nib
  21.     {                        // geladen wurde, d.h. die Default-Defaults sind schon
  22.                               // vom Preferences Manager gesetzt!
  23.     if(self==[Article class])
  24.         {
  25.         [self prefsChanged];
  26.         [ERROR_MANAGER addObserver:self 
  27.             selector:@selector(prefsChanged) forError:ENOTEPrefsChanged];
  28.         }
  29.     return self;
  30.     }
  31.  
  32.  
  33. + prefsChanged;
  34.     {
  35.     showAuthor=[NXApp defaultBoolValue:DEFAULT_SHOW_AUTHOR];    
  36.     showSubject=[NXApp defaultBoolValue:DEFAULT_SHOW_SUBJECT];    
  37.     showSize=[NXApp defaultBoolValue:DEFAULT_SHOW_SIZE];
  38.     smallIs=[NXApp defaultIntValue:DEFAULT_SMALL_ARTICLE];    
  39.     largeIs=[NXApp defaultIntValue:DEFAULT_LARGE_ARTICLE];    
  40.     return self;
  41.     }
  42.  
  43. + setSortType:(int)t
  44. {
  45.     sortType=t;
  46.     
  47.     return self;
  48. }
  49.  
  50. + (int)sortType
  51. {
  52.     return sortType;
  53. }
  54.  
  55. - initWithNumber:(long)number
  56. {
  57.    [self initTextCell:NULL];
  58.    [self setWrap:NO];
  59.    size=0;
  60.    unread=TRUE;
  61.    myNumber=number;
  62.    myHeader.fieldBody=(char **)calloc(FIELD_COUNT,sizeof(char *));
  63.    timeOfPosting=0;
  64.    authorRealName=NULL;
  65.    killed=FALSE;
  66.    return self;
  67. }
  68.  
  69. - composeTitle
  70. {
  71.    char *buf,*p=NULL;
  72.     BOOL a=FALSE;
  73.     BOOL b=FALSE;
  74.     int from,to,tsize=1;
  75.     
  76.     if(showSubject && (p=myHeader.fieldBody[SUBJECT])){
  77.        a=TRUE;
  78.         tsize+=strlen(p);
  79.     }
  80.     
  81.     if(showAuthor && (myHeader.fieldBody[FROM]!=NULL)){
  82.       rfc822_realname(myHeader.fieldBody[FROM],&from,&to);
  83.          if(from<to)
  84.                 b=TRUE;
  85.                 tsize+=to-from+6;
  86.     }
  87.  
  88.     buf=calloc(tsize,sizeof(char));
  89.     if(a) strcpy(buf,p);
  90.     if(b){
  91.        strcat(buf," (");
  92.       strncat(buf,myHeader.fieldBody[FROM]+from,to-from+1);
  93.       strcat(buf,")");
  94.    }
  95.  
  96.  
  97.    [self setStringValueNoCopy:buf shouldFree:YES];
  98.     
  99.     return self;
  100. }
  101.  
  102. - parseHeader:(NXStream *)headerStream;
  103. {
  104.    char *stream_buffer;
  105.    int len,a;
  106.  
  107.    NXGetMemoryBuffer(headerStream,&stream_buffer,&len,&a);
  108.    parse_header(stream_buffer, len, myHeader.fieldBody, h_field_name, FIELD_COUNT,YES);
  109.  
  110.    return self;
  111. }
  112.  
  113. -free
  114. {
  115.    int i;
  116.  
  117.    for(i=0;i<FIELD_COUNT;i++)
  118.       if(myHeader.fieldBody[i]!=NULL)
  119.          free(myHeader.fieldBody[i]);
  120.    free(myHeader.fieldBody);
  121.    if(authorRealName!=NULL)
  122.       free(authorRealName);
  123.    return([super free]);
  124. }
  125.  
  126. - (long)number
  127. {
  128.    return myNumber;
  129. }
  130.  
  131. - (headerDesc *)header
  132. {
  133.    return &myHeader;
  134. }
  135.  
  136. - (time_t)time
  137. {
  138.    if((timeOfPosting==0)&&(myHeader.fieldBody[DATE]!=NULL)){
  139.       timeOfPosting=parsedate(myHeader.fieldBody[DATE]);
  140.       if(timeOfPosting==-1){
  141.          timeOfPosting=0;
  142.          free(myHeader.fieldBody[DATE]);
  143.          myHeader.fieldBody[DATE]=NULL;
  144.       }
  145.    }
  146.  
  147.    return timeOfPosting;
  148. }
  149.  
  150. - (const char *)realName;
  151. {
  152.    if((authorRealName==NULL)&&(myHeader.fieldBody[FROM]!=NULL)){
  153.       int from,to;
  154.       rfc822_realname(myHeader.fieldBody[FROM],&from,&to);
  155.       if(from<to){
  156.          authorRealName=(char *)malloc((to-from+2)*sizeof(char));
  157.          strncpy(authorRealName,myHeader.fieldBody[FROM]+from,to-from+1);
  158.          authorRealName[to-from+1]='\0';
  159.       }
  160.    }
  161.  
  162.    return authorRealName;
  163. }
  164.  
  165. - setRead
  166. {
  167.    unread=FALSE;
  168.    return self;
  169. }
  170.  
  171. - setUnread
  172. {
  173.    unread=TRUE;
  174.    return self;
  175. }
  176.  
  177. - (BOOL)isRead
  178. {
  179.    return((unread==FALSE)||(killed==TRUE));
  180. }
  181.  
  182. - kill
  183. {
  184.    killed=TRUE;
  185.    return self;
  186. }
  187.  
  188. - unkill
  189. {
  190.    killed=FALSE;
  191.    return self;
  192. }
  193.  
  194. - (BOOL)isKilled
  195. {
  196.    return killed;
  197. }
  198.  
  199. - setTextAttributes:textObj
  200. {
  201.    [super setTextAttributes:textObj];
  202.    if (unread==FALSE)
  203.       [textObj setTextGray:NX_DKGRAY];
  204.    else
  205.       [textObj setTextGray:NX_BLACK];      
  206.    return textObj;
  207. }
  208.  
  209. - unsetTag
  210. {
  211.    myTag=0;
  212.    return self;
  213. }
  214.  
  215. - setTag
  216. {
  217.    myTag=1;
  218.    return self;
  219. }
  220.  
  221. - (BOOL)isTaged
  222. {
  223.    return((myTag==1)&&(killed==FALSE));
  224. }
  225.  
  226. - (int)size
  227. {
  228.    return size;
  229. }
  230.  
  231. - setSize:(int)asize;
  232. {
  233.    size=asize;
  234.    return self;
  235. }
  236.  
  237.  
  238.  
  239. - (int)lines;
  240.     {
  241.     return lines;
  242.     }
  243.  
  244.  
  245. - setLines:(int)lineCount;
  246.     {
  247.     lines=lineCount;
  248.     return self;
  249.     }
  250.     
  251. //------------------------------------
  252. // MiscCompare protocol implementation
  253. //------------------------------------
  254. - (int)compare:anObject
  255. {
  256.   int result=0;
  257.   BOOL r1,r2;
  258.   const char *s1,*s2;
  259.   headerDesc *h1,*h2;
  260.  
  261.   switch (sortType) {
  262.     case SORT_BY_DATE:
  263.        result=[self time]-[anObject time];
  264.        break;
  265.     case SORT_BY_SUBJECT:
  266.           h1=[self header];
  267.          h2=[anObject header];
  268.          if(!h1 || !h2){
  269.              NXLogError("Article.m: article header is NULL pointer");
  270.             return 0;
  271.          }
  272.        s1=plain_subject(h1->fieldBody[SUBJECT],&r1);
  273.        s2=plain_subject(h2->fieldBody[SUBJECT],&r2);
  274.  
  275.        if((s1==NULL)&&(s2==NULL)) result=0;
  276.        else if(s1==NULL) result=-1;
  277.        else if(s2==NULL) result=1;
  278.        else
  279.           result=strcasecmp(s1,s2);
  280.        if(result==0)
  281.           if(r1!=r2)
  282.              result=(r1? 1:-1);
  283.           else
  284.              result=[self time]-[anObject time];
  285.        break;
  286.     case SORT_BY_NUMBER:
  287.        result=[self number]-[anObject number];
  288.        break;
  289.     case SORT_BY_REAL_NAME:
  290.        s1=[self realName];
  291.        s2=[anObject realName];
  292.        if((s1==NULL)&&(s2==NULL)) result=0;
  293.        else if(s1==NULL) result=-1;
  294.        else if(s2==NULL) result=1;
  295.        else
  296.           result=strcasecmp(s1,s2);
  297.        break;
  298.   }
  299.  
  300.   return result;
  301. }
  302.  
  303. //-----------------------------------------------------------
  304. // fancy drawing...
  305. //-----------------------------------------------------------
  306.  
  307. #define IMAGEMARGIN 1.0
  308.  
  309. - calcCellSize:(NXSize *)theSize inRect:(const NXRect *)aRect
  310.     {
  311.     [super calcCellSize:theSize inRect:aRect];
  312.     theSize->height+=1;
  313.     return self;
  314.     }
  315.  
  316.  
  317. - drawInside:(const NXRect *)cellFrame inView:controlView
  318.     {
  319.     static NXImage    *dotImages[] = { nil, nil, nil };
  320.     NXRect             rect = *cellFrame;
  321.     NXPoint         imageOrigin;
  322.     NXSize             dotSize;
  323.     int                sizecat;
  324.     struct _cFlags1    buf;
  325.         
  326.     if(!dotImages[0])
  327.         {
  328.         dotImages[0] = [NXImage findImageNamed:"Article-short"];
  329.         dotImages[1] = [NXImage findImageNamed:"Article-medium"];
  330.         dotImages[2] = [NXImage findImageNamed:"Article-long"];
  331.         }        
  332.     [dotImages[2] getSize:&dotSize];
  333.  
  334.     PSsetgray((cFlags1.state || cFlags1.highlighted) ? NX_WHITE : NX_LTGRAY);
  335.     NXRectFill(cellFrame);
  336.  
  337.     if(showSize && (lines>0))
  338.         {
  339.         imageOrigin.x = NX_MAXX(cellFrame) - IMAGEMARGIN * 2.0 - dotSize.width;
  340.         imageOrigin.y = NX_Y(cellFrame) + NX_HEIGHT(cellFrame) -
  341.                         (NX_HEIGHT(cellFrame) - dotSize.height) / 2.0;
  342.         if(lines<=smallIs)
  343.             sizecat=0;
  344.         else if(lines<=largeIs)
  345.             sizecat=1;
  346.         else
  347.             sizecat=2;
  348.         [dotImages[sizecat] composite:NX_SOVER toPoint:&imageOrigin];
  349.         NX_WIDTH(&rect) -= (dotSize.width + IMAGEMARGIN * 2.0 - NX_X(&rect));
  350.         }
  351.     buf=cFlags1;
  352.     cFlags1.highlighted=cFlags1.state=0;
  353.     [super drawInside:&rect inView:controlView];
  354.     cFlags1=buf;
  355.     
  356.     PSsetgray(NX_DKGRAY);
  357.     if (cFlags1.state || cFlags1.highlighted)
  358.         {
  359.         NXRect rectArray[2];
  360.  
  361.         NXSetRect(&(rectArray[0]),NX_X(cellFrame),NX_Y(cellFrame),
  362.                 NX_WIDTH(cellFrame),1);
  363.         NXSetRect(&(rectArray[1]),NX_X(cellFrame),NX_MAXY(cellFrame)-1,
  364.                 NX_WIDTH(cellFrame), 1.0);
  365.         NXRectFillList(rectArray, 2);
  366.         }
  367.     return self;
  368.     }
  369.  
  370.  
  371. - highlight:(const NXRect *)cellFrame inView:controlView lit:(BOOL)flag
  372.     {
  373.     if(cFlags1.highlighted != flag)
  374.         {
  375.         cFlags1.highlighted = flag;
  376.         [self drawInside:cellFrame inView:controlView];
  377.         }
  378.     return self;
  379.     }
  380.  
  381.  
  382.  
  383. @end
  384.